import { HttpClient } from '@/config/httpClient/HttpClient.ts'
import type { HttpRequestInterceptor, HttpResponseInterceptor } from '@/config/httpClient/HttpInterceptor.ts'
import { useAccountStore } from '@/config/store/UseAccountStore.ts'
import { AxiosError, AxiosHeaders, type AxiosHeaderValue, type AxiosInterceptorOptions, type AxiosRequestConfig, type AxiosResponse } from 'axios'
import { type Router } from 'vue-router'


/**
 * 给请求设置认证请求头
 * @param request 请求
 * @param value 请求头 Authorization 的值
 * @param rewrite 是否覆盖
 */
function setAuthorizationHeader(request: AxiosRequestConfig, value: AxiosHeaderValue, rewrite: any = false): void {
    const headers: AxiosHeaders = request.headers as any ?? new AxiosHeaders()
    headers.setAuthorization(value, rewrite)
    request.headers = headers
}

/**
 * 请求拦截器: 附加认证请求头
 */
export class AuthenticationInterceptor implements HttpRequestInterceptor {

    options: AxiosInterceptorOptions = {
        synchronous: true,
        runWhen(_) {
            return true
        },
    }


    public onFulfilled(request: AxiosRequestConfig): AxiosRequestConfig | Promise<AxiosRequestConfig> {
        const { access, isLogin } = useAccountStore()
        if (isLogin) {
            setAuthorizationHeader(request, 'Bearer ' + access)
        }

        return request
    }

}


/**
 * 响应拦截器: 处理认证失败和令牌刷新
 */
export class AuthenticationRefreshInterceptor implements HttpResponseInterceptor {

    // @ts-ignore
    private readonly httpClient: HttpClient

    private readonly routerSupplier: () => Router


    public constructor(httpClient: HttpClient, router: () => Router) {
        this.httpClient = httpClient
        this.routerSupplier = router
    }

    async onRejected(error: any): Promise<any> {
        if (!error || !(error instanceof AxiosError)) {
            return Promise.reject(error)
        }
        const status = error.response?.status ?? -1

        if (status === 401 || status === 403) {
            const { clearAccessToken } = useAccountStore()
            clearAccessToken()
            await this.routerSupplier().push('/login')
            // return this.httpClient.request(error.config!)
        }

        return Promise.reject(error)
    }

    onFulfilled(response: AxiosResponse): AxiosResponse | Promise<AxiosResponse> {
        return Promise.resolve(response)
    }

}
